﻿using System.Collections.Generic;
using AzureGames.Domain.Services;
using InMemory = AzureGames.Data.InMemory;
using Implementation = AzureGames.Data.Implementation;
using AzureGames.Domain.Handlers;
using Model = AzureGames.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using AzureGames.Data;
using System.Threading;
using AzureGames.Domain.Models;
using System.Linq;
using AzureGames.Domain.Tests.Helper;
using AzureGames.Model;
using System.Web.Mvc;
using Microsoft.WindowsAzure;
using System.Configuration;

namespace AzureGames.Domain.Tests
{


    /// <summary>
    ///This is a test class for GetGameDefinitionTest and is intended
    ///to contain all GetGameDefinitionTest Unit Tests
    ///</summary>
    [TestClass()]
    public class RegisterNewGameTests
    {
       
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///A test for RegisterNewGame Constructor
        ///</summary>
        [TestMethod()]
        public void RegisterNewGameConstructorInMemoryTest()
        {
            RegisterNewGameConstructorTest(new InMemory.BoardRepository(),
                                            new InMemory.GameDefinitionRepository(),
                                            new InMemory.NotificationRepository(),
                                            new InMemory.UserRepository(), 
                                            new InMemory.PlayerRepository(),                                            
                                            new InMemory.StatisticsRepository(), 
                                            new InMemory.StatisticsRepository());
        }

        /// <summary>
        /// Test for single player start for unauthenticated user
        /// </summary>
        [TestMethod()]
        public void CreateNewGameSinglePlayerAnonymousInMemoryTest()
        {
            CreateNewGameSinglePlayerAnonymousTest(new InMemory.BoardRepository(), 
                                                   new InMemory.GameDefinitionRepository(), 
                                                    new InMemory.NotificationRepository(), 
                                                    new InMemory.PlayerRepository(), 
                                                    new InMemory.StatisticsRepository(), 
                                                    new InMemory.StatisticsRepository());
        }

        /// <summary>
        ///A test for RegisterNewGame Constructor
        ///</summary>
        [TestMethod()]
        public void RegisterNewGameConstructorImplementationTest()
        {
             CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                // Provide the configSetter with the initial value
                configSetter(ConfigurationManager.AppSettings[configName]);
            });

             RegisterNewGameConstructorTest(new Implementation.BoardRepository(),
                                            new Implementation.GameDefinitionRepository(),
                                            new Implementation.NotificationRepository(),
                                            new Implementation.UserRepository(),
                                            new Implementation.PlayerRepository(),
                                            new Implementation.UserStatisticsRepository(),
                                            new Implementation.GameStatisticsRepository());
        }

        /// <summary>
        /// Test for single player start for unauthenticated user
        /// </summary>
        [TestMethod()]
        public void CreateNewGameSinglePlayerAnonymousImplementationTest()
        {
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                // Provide the configSetter with the initial value
                configSetter(ConfigurationManager.AppSettings[configName]);
            });

            CreateNewGameSinglePlayerAnonymousTest(new Implementation.BoardRepository(),
                                                   new Implementation.GameDefinitionRepository(),
                                                    new Implementation.NotificationRepository(),
                                                    new Implementation.PlayerRepository(),
                                                    new Implementation.UserStatisticsRepository(),
                                                    new Implementation.GameStatisticsRepository());
        }

        private static void CreateNewGameSinglePlayerAnonymousTest(IBoardRepository boardRepository, IGameDefinitionRepository gameDefinitionRepository, INotificationRepository notificationRepository, IPlayerRepository playerRepository, IUserStatisticsRepository userstatisticsRepository, IGameStatisticsRepository gamestatisticsRepository)
        {
            string session = "theSessionID";

            //var notificationService = NotificationService.Instance.IntializeNotificationService(notificationRepository);
            //notificationService.AddSession(session, Guid.Empty.ToString());

            // handlers
            Handlers.CreateNewGame createNewGame = new CreateNewGame(boardRepository, gameDefinitionRepository, playerRepository, userstatisticsRepository, gamestatisticsRepository);
            Handlers.GetGameBoard getGameBoardHandler = new GetGameBoard(boardRepository, gameDefinitionRepository, playerRepository);

            GameBoard board = createNewGame.Execute(1, new List<string> { Guid.Empty.ToString(), "1:BE4813EF-4A23-49FF-BDF0-8139177C9C93" });
            Assert.AreEqual(1, board.CSSFiles.Count);
            Assert.AreEqual(8, board.JavascriptFiles.Count);
            Assert.AreEqual(9, board.Resources.Count);
            Assert.AreEqual(4, board.Properties.Count);
            Assert.AreEqual(2, board.GamePlayers.Count);


            Assert.AreEqual(board.State, Model.Board.Active.ToString());

            // was the anonymous player notified 
            //var notifications = notificationService.GetNotifications(session, 10);

            // there should be no notifications
            //Assert.IsTrue(notifications.Count() == 0);
        }


        private static void RegisterNewGameConstructorTest(IBoardRepository boardRepository, IGameDefinitionRepository gameDefinitionRepository, INotificationRepository notificationRepository, IUserRepository userRepository, IPlayerRepository playerRepository, IUserStatisticsRepository userstatisticsRepository, IGameStatisticsRepository gamestatisticsRepository)
        {
            //var notificationService = NotificationService.Instance.IntializeNotificationService(notificationRepository);

            // handlers            
            //RegisterNewGame registerNewGameHandler = new RegisterNewGame(boardRepository, gameDefinitionRepository, notificationRepository, playerRepository, userstatisticsRepository, gamestatisticsRepository);
            //GetGameBoard getGameBoardHandler = new GetGameBoard(boardRepository, gameDefinitionRepository, playerRepository);


            //var users = new List<User>
            //                {
            //                    userRepository.GetUser("DF2AA2FD-6AA8-474F-B29B-BCCD8247D397".ToLower()),
            //                    userRepository.GetUser("2F851A61-249B-4942-9FE4-2276D39183EF".ToLower())
            //                };


            //// both users navigate to the site
            //// note: using the identifier as the sessionid for convenience
            ////       empty guid to indicate they are not logged in yet
            //notificationService.AddSession(users[0].NameIdentifier, Guid.Empty.ToString());
            //notificationService.AddSession(users[1].NameIdentifier, Guid.Empty.ToString());

            //// login player 1
            //userRepository.LoginUser(users[0].NameIdentifier);
            //notificationService.AddSession(users[0].NameIdentifier, users[0].ID);

            //// login player 2
            //userRepository.LoginUser(users[1].NameIdentifier);
            //notificationService.AddSession(users[1].NameIdentifier, users[1].ID);

            //var stats = gamestatisticsRepository.GetGameStatistics(1, Model.Statistics.RANGE.ThisWeek);
            //int createdGames = stats.Count == 0 ? 0 : stats[0].CreatedGames;


            //// user 1 registers for amazons
            //GameBoard board = registerNewGameHandler.Execute(1, users[0].ID);

            //Assert.AreEqual(board.State, Model.Board.Created.ToString());
            //Assert.AreEqual(board.GamePlayers.Count, 1);

            //Guid id = board.ID;


            //// no notifications yet
            //var notifications = notificationService.GetNotifications(users[0].NameIdentifier, 10);
            //Assert.IsTrue(notifications.Count() == 0);
            //notifications = notificationService.GetNotifications(users[1].NameIdentifier, 10);
            //Assert.IsTrue(notifications.Count() == 0);

            //// user 2 registers for amazons (the boardid returned should be the same)
            //Assert.AreEqual(registerNewGameHandler.Execute(1, users[1].ID).ID.ToString(), board.ID.ToString());

            //Thread.CurrentThread.Join(200);

            //board = getGameBoardHandler.Execute(board.ID);
            //Assert.AreEqual(board.State, Model.Board.Active.ToString());
            //Assert.AreEqual(id, board.ID);
            //Assert.AreEqual(2, board.GamePlayers.Count);

            //Assert.AreEqual(users[0].ID, board.GamePlayers[0].ID);
            //Assert.AreEqual(users[1].ID, board.GamePlayers[1].ID);


            //// TODO: notifications
            //// only the first user should have been notified
            ////notifications = notificationService.GetNotifications(users[0].NameIdentifier, 10);
            ////Assert.IsTrue(notifications.Count() == 1);
            ////notifications = notificationService.GetNotifications(users[1].NameIdentifier, 10);
            //Assert.IsTrue(notifications.Count() == 0);

            //stats = gamestatisticsRepository.GetGameStatistics(1, Model.Statistics.RANGE.ThisWeek);

            //Assert.IsFalse(stats[0].CreatedGames == createdGames);

        }
    }
}
